package com.ltmonitor.jt808.service.impl;

import java.util.Collection;
import java.util.Date;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ltmonitor.app.GlobalConfig;
import com.ltmonitor.app.GpsConnection;
import com.ltmonitor.app.ServiceLauncher;
import com.ltmonitor.entity.PlatformState;
import com.ltmonitor.entity.TerminalCommand;
import com.ltmonitor.jt808.protocol.T808Message;
import com.ltmonitor.jt808.service.IAckService;
import com.ltmonitor.jt808.service.ICommandHandler;
import com.ltmonitor.jt808.service.ICommandParseService;
import com.ltmonitor.jt808.service.IJT808Server;
import com.ltmonitor.jt808.service.IMediaService;
import com.ltmonitor.jt808.service.IMessageSender;
import com.ltmonitor.jt808.service.IMultiPacketMessageService;
import com.ltmonitor.jt808.service.IT808Manager;
import com.ltmonitor.jt808.service.ITransferGpsService;
import com.ltmonitor.server.mina.IJT808TransferService;
import com.ltmonitor.server.mina.JT808TransferQueue;
import com.ltmonitor.service.IPlatformStateService;

/**
 * 808Gps服务
 * 
 * @author DELL
 * 
 */
@Service("t808Manager")
public class T808Manager implements IT808Manager {

	private static Logger logger = Logger.getLogger(T808Manager.class);
	/**
	 * gps监听端口
	 */

	@Value("#{config.listenPort}")
	private int listenPort;
	/**
	 * 是否启用808转发
	 */
	@Value("#{config.enable808Tranasfer}")
	private boolean enable808Tranasfer = false;
	/**
	 * 808转发地址端口
	 */
	@Value("#{config.third808ServerPort}")
	private int third808ServerPort = 0;
	/**
	 * 808转发地址
	 * 	 */
	@Value("#{config.third808ServerIp}")
	private String third808ServerIp;

	/**
	 * 808server
	 */
	@Resource(name = "jt808TcpNettyServer")
	private IJT808Server jt808Server;

	// private static ConcurrentLinkedQueue<T808Message> dataQueue = new
	// ConcurrentLinkedQueue();

	/**
	 * 下发流水号
	 */
	private static int serialNo = 0;
	/**
	 * 命令解析服务
	 */
	@Autowired
	private ICommandParseService commandService;
	@Autowired
	private IPlatformStateService platformStateService;

	// private Thread processRealDataThread;
	/**
	 * 应答服务
	 */
	@Autowired
	private IAckService ackService;
	/**
	 * 拍照解析服务
	 */
	@Autowired
	private IMediaService mediaService;

	/**
	 * 分包聚合成完整包服务
	 */
	@Autowired
	private IMultiPacketMessageService multiPacketMessageService;

	/**
	 * 809转发
	 */
	@Autowired
	private ITransferGpsService transferGpsService;
	/**
	 * 808转发服务
	 */
	@Autowired
	private IJT808TransferService jt808TransferService;

	public static int getSerialNo() {
		if (serialNo >= (Short.MAX_VALUE - 1))
			serialNo = 0;
		return serialNo++;
	}

	public Collection<GpsConnection> getGpsConnections() {
		return getJt808Server().getGpsConnections();
	}

	// 发送数据
	private boolean send(String simNo, byte[] msg) {
		boolean res = getJt808Server().send(simNo, msg);
		return res;
	}

	//发送消息
	public boolean Send(T808Message msg) {
		msg.getHeader().setMessageSerialNo((short) getSerialNo());
		// msg.setPacketDescr(strMsg);
		boolean res = send(msg.getSimNo(), msg.WriteToBytes());
		GlobalConfig.putMsg(msg);
		return res;
	}

	@Transactional
	public boolean StartServer() {
		boolean res = getJt808Server().start();
		if (res) {
			JT808TransferQueue.enable808Tranasfer = enable808Tranasfer;
			if (this.enable808Tranasfer) {
				//启动808转发服务
				JT808TransferQueue.port = (this.third808ServerPort);
				JT808TransferQueue.serverIp = (this.third808ServerIp);
				this.jt808TransferService.startTransfer();
			}
			try {
				PlatformState ps = platformStateService.getPlatformState();
				ps.setGpsServerDate(new Date());
				ps.setGpsServerState(PlatformState.STATE_START);
				platformStateService.saveOrUpdate(ps);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			// getCommandService().Start();

			this.commandService.setOnRecvCommand(new ICommandHandler() {

				@Override
				public boolean OnRecvCommand(T808Message tm, TerminalCommand tc) {
					if (getJt808Server().isOnline(tc.getSimNo()) == false) {
						tc.setStatus(TerminalCommand.STATUS_OFFLINE);
						return false;
					} else {
						boolean res = Send(tm);
						tc.setSN(tm.getHeader().getMessageSerialNo());
						tc.setStatus(res ? TerminalCommand.STATUS_PROCESSING
								: TerminalCommand.STATUS_FAILED);
						return res;
					}
				}
			});

			ackService.setMessageSender(new IMessageSender() {
				@Override
				public void Send808Message(T808Message tm) {
					Send(tm);
				}
			});
			
			
			mediaService.setMessageSender(new IMessageSender() {
				@Override
				public void Send808Message(T808Message tm) {
					Send(tm);
				}
			});			

			multiPacketMessageService.setMessageSender(new IMessageSender() {
				@Override
				public void Send808Message(T808Message tm) {
					Send(tm);
				}
			});
			
			multiPacketMessageService.start();
			transferGpsService.start();
		}
		return res;
	}

	
	public void StopServer() {
		try {
			PlatformState ps = platformStateService.getPlatformState();
			ps.setGpsServerDate(new Date());
			ps.setGpsServerState(PlatformState.STATE_STOP);
			platformStateService.saveOrUpdate(ps);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		try {
			getJt808Server().Stop();
			multiPacketMessageService.Stop();
			transferGpsService.stop();
			if (jt808TransferService != null)
				this.jt808TransferService.stop();
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	public void setJt808Server(IJT808Server jt808Server) {
		this.jt808Server = jt808Server;
	}

	public IJT808Server getJt808Server() {
		return jt808Server;
	}

	public void setCommandService(ICommandParseService commandService) {
		this.commandService = commandService;
	}

	public ICommandParseService getCommandService() {
		return commandService;
	}

	public void setAckService(IAckService ackService) {
		this.ackService = ackService;
	}

	public IAckService getAckService() {
		return ackService;
	}

	public int getListenPort() {
		return listenPort;
	}

	public void setListenPort(int listenPort) {
		this.listenPort = listenPort;
	}

	public ITransferGpsService getTransferGpsService() {
		return transferGpsService;
	}

	public void setTransferGpsService(ITransferGpsService transferGpsService) {
		this.transferGpsService = transferGpsService;
	}

	public IMediaService getMediaService() {
		return mediaService;
	}

	public void setMediaService(IMediaService mediaService) {
		this.mediaService = mediaService;
	}

	public boolean isEnable808Tranasfer() {
		return enable808Tranasfer;
	}

	public void setEnable808Tranasfer(boolean enable808Tranasfer) {
		this.enable808Tranasfer = enable808Tranasfer;
	}

	public int getThird808ServerPort() {
		return third808ServerPort;
	}

	public void setThird808ServerPort(int third808ServerPort) {
		this.third808ServerPort = third808ServerPort;
	}

	public String getThird808ServerIp() {
		return third808ServerIp;
	}

	public void setThird808ServerIp(String third808ServerIp) {
		this.third808ServerIp = third808ServerIp;
	}

	public IJT808TransferService getJt808TransferService() {
		return jt808TransferService;
	}

	public void setJt808TransferService(
			IJT808TransferService jt808TransferService) {
		this.jt808TransferService = jt808TransferService;
	}

}
